#ifndef DESIGN_PATTERNS_PROTOTYPE_HPP
#define DESIGN_PATTERNS_PROTOTYPE_HPP

#include <string>
#include <map>

namespace DesignPatterns {
        class record;
        class car_record;
        class bike_record;
        class plane_record;
        class client;
}

/// @brief Creational pattern : prototype

enum record_type
{
        CAR,
        BIKE,
        PLANE
};

// @brief Abstract base class (prototype class)
class DesignPatterns::record
{
public:
        record() {}
        ~record() {}
        virtual record* clone() = 0;
        virtual void print() = 0;
};

// @brief concrete prototype 1
class DesignPatterns::car_record : public DesignPatterns::record
{
public: 
        car_record(std::string car_name, int id);
        car_record(car_record& car);
        ~car_record() {}
        record* clone();
        void print();
private:
        std::string m_car_name;
        int m_car_id;
};

// @brief concrete prototype 2
class DesignPatterns::bike_record : public DesignPatterns::record
{
public: 
        bike_record(std::string bike_name, int id);
        bike_record(bike_record& bike);
        ~bike_record() {}
        record* clone();
        void print();
private:
        std::string m_bike_name;
        int m_bike_id;
};

// @brief concrete prototype 3
class DesignPatterns::plane_record : public DesignPatterns::record
{
public: 
        plane_record(std::string plane_name, int id);
        plane_record(plane_record& plane);
        ~plane_record() {}
        record* clone();
        void print();
private:
        std::string m_plane_name;
        int m_plane_id;
};

// @brief client
class DesignPatterns::client
{
public:
        record* create_record(record_type type);
        client();
        ~client();
private: 
        std::map<record_type, record* > m_record;
};

#endif //DESIGN_PATTERNS_PROTOTYPE_HPP
